#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <stdarg.h>
#include <errno.h>
#include <pthread.h>

int     make_socket(int portnum);
void    thread_setup(pthread_attr_t *attrp);
int     do_popen(int fd, const char* program_name);
void   *handle_request(void * fdptr);
void    write_http_response(int fd, const char *);
int     try_request(int fd, char *);

int
main(int argc, char *argv[])
{
  int sock, fd;
  int *fdptr;
  pthread_t worker;
  pthread_attr_t attr;  

  if (argc != 2) {
    printf("%s", "usage: server [port]\n");
    exit(EXIT_FAILURE);
  }

  sock = make_socket(atoi(argv[1]));

  thread_setup(&attr);

  while (1) {
    // fd = accept(sock, (struct sockaddr *)&fsin, &alen);
     fd = accept(sock, NULL, NULL);
     if (fd < 0) {
       fprintf(stderr, "accept failed: %s\n", strerror(errno));
       exit(EXIT_FAILURE);
     }
     fdptr = malloc(sizeof(int));
     *fdptr = fd;
     pthread_create(&worker, &attr, handle_request, fdptr);
  }

  exit(EXIT_SUCCESS);
}

void thread_setup(pthread_attr_t *attrp)
{
  pthread_attr_init(attrp);
  pthread_attr_setdetachstate(attrp, PTHREAD_CREATE_DETACHED);
}

void *handle_request(void *fdptr)
{
  FILE *fpin;
  int fd;
  //pthread_mutex_t mut;

  //pthread_mutex_lock(&mut);

  char request[128];

  fd = *(int *)fdptr;
  free(fdptr);
  if (NULL == (fpin = fdopen(dup(fd), "r")))
    perror("fdopen failed in handle_request");

  fgets(request, 128, fpin);
  printf("\n--------begin request-----------\n");
  printf("%s", request);
  printf("\n-------end request------------\n");
  if (strstr(request, "GET") == request) {
    write_http_response(fd,  
			"200 OK\r\nContent-Type: text/html\r\n\r\n");

    //printf("%s", str);
    if (try_request(fd, request) != 0)
      do_popen(fd, "python info.py");
    printf("\n-------end response------------\n");
  } else {
    write_http_response(fd, "501 Not Implemented\r\nContent-Type: text/plain\r\n\r\n");
    const char body[] = "This web server does not know how to handle that type of request";
    FILE *fpout = fdopen(dup(fd), "w");
    fprintf(fpout, "%s", body);
    fclose(fpout);
  }
  fclose(fpin);
  //pthread_mutex_unlock(&mut);
}

int do_popen(int fd, const char* program_name)
{
  FILE *pipe_in;
  FILE *sock_out;
  if (NULL == (sock_out = fdopen(fd, "w")))
    perror("fdopen failed in do_popen");
  char line[130];
  //char buffer[130]; 
  pipe_in = popen(program_name, "r");
  while (fgets(line, sizeof(line), pipe_in) != NULL ) {   
    fprintf(sock_out, "%s", line);
  }
  /* close the pipe! */
  pclose(pipe_in);
  fclose(sock_out);
  
  return 0;
}

void write_http_response(int fd, const char *status)

{
  FILE *fp;
  if (NULL == (fp = fdopen(dup(fd), "w")))
    perror("fdopen failed in write_http_response");
  fprintf(fp, "HTTP/1.0 %s", status);
  printf("\r\n-------begin response------------\r\n");
  printf("HTTP/1.0 %s", status);

  fclose(fp);
}

int try_request(int fd, char *request)
{
  char str[32];
  sscanf(request, "GET /%s", str);
  printf("Request in try_request is: %s", request);
  if (strstr(str, "reboot.py?passwd=cspp") == str) {
    do_popen(fd, "python reboot.py");
    return 0;
  } else if (strstr(str, "kill_process.py") == str) {
    char arg[64];
    char pid[16];
    sscanf(str, "kill_process.py?pid=%s", pid);
    sprintf(arg, "python kill_process.py %s", pid);
     
    printf("****%s****", arg);
    do_popen(fd, arg);
    return 0;
  }
  return 1;
  
}
